//===- DeadCodeElimination.cpp - Eliminate dead iteration  ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If values calculated within an iteration are not used later on the iteration
// can be removed entirely. This pass removes such iterations.
//===----------------------------------------------------------------------===//

#include "polly/Dependences.h"
#include "polly/LinkAllPasses.h"
#include "polly/ScopInfo.h"

//#include "/home/sameer/svn/polly/cloog_src/isl/isl_map_private.h"
//#include "isl/basic_map.h"
#include "isl/union_map.h"
#include "isl/map.h"
#include "isl/set.h"


using namespace llvm;
using namespace polly;

namespace {

  class DeadCodeElim : public ScopPass {

  public:
    static char ID;
    explicit DeadCodeElim() : ScopPass(ID) {}

    virtual bool runOnScop(Scop &S);
    void printScop(llvm::raw_ostream &OS) const;
    void getAnalysisUsage(AnalysisUsage &AU) const;
  };
}

char DeadCodeElim::ID = 0;


bool DeadCodeElim::runOnScop(Scop &S) {
	Dependences *D = &getAnalysis<Dependences>();

	int dependencyKinds_WAW = Dependences::TYPE_WAW;
	int dependencyKinds_RAW = Dependences::TYPE_RAW;

	isl_union_map *dependences_WAW = D->getDependences(dependencyKinds_WAW);
	isl_union_map *dependences_RAW = D->getDependences(dependencyKinds_RAW);
	isl_union_set* pOriginalDomain = S.getDomains();
	printf( "original statements: \n");
	isl_union_set_dump( pOriginalDomain );
	printf("\n");

	printf( "Iterations for WAW \n");
	isl_union_map_dump( dependences_WAW );
	printf("\n");

	printf( "Iterations for RAW \n");
	isl_union_map_dump( dependences_RAW );
	printf("\n");

	isl_union_map* pIterationsToDelteDomainsMap	= isl_union_map_subtract( dependences_WAW , dependences_RAW );
	isl_union_set* pIterationsToDelete		= isl_union_map_domain( pIterationsToDelteDomainsMap ); //Get the domain only of the map , this represents statements to delete.

	printf( " Statements to delete: \n");
	isl_union_set_dump( pIterationsToDelete );
	printf("\n");

	isl_union_set* pNewDomains = isl_union_set_subtract( pOriginalDomain , pIterationsToDelete   );

	printf( " Statements to execute are \n" );
	isl_union_set_dump( pNewDomains );


	printf(" Now filling the statements with the new domains \n");
	printf(" ***************************************************\n \n");
	for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI){

			ScopStmt*	Stmt				= *SI;
			isl_set*	pStmtDomain			= Stmt->getDomain();
			isl_union_set* pStmDomainUnion	= isl_union_set_from_set( pStmtDomain );

			//Intersect the statement domain with the original union set to get the new domain for the current statement.
			isl_union_set*	pNewStmtDomainUnion	= isl_union_set_intersect( pStmDomainUnion , isl_union_set_copy( pNewDomains ) );

			//Turn the union set into a set.
			isl_set* pNewStmtDomain = isl_set_from_union_set( pNewStmtDomainUnion );
			printf( "New domain for %s is:\n" , Stmt->getBaseName() );
			isl_set_dump( pNewStmtDomain );

			Stmt->restrictDomain( pNewStmtDomain );
	}

	isl_union_set_free( pNewDomains );
	printf( "---------------------------------------------------------------------\n");

	return false;
}


void DeadCodeElim::printScop(raw_ostream &OS) const {
}

void DeadCodeElim::getAnalysisUsage(AnalysisUsage &AU) const {
  ScopPass::getAnalysisUsage(AU);
  AU.addRequired<Dependences>();
}

INITIALIZE_PASS_BEGIN(DeadCodeElim, "polly-dce",
                      "Polly - Remove dead iterations", false, false)
INITIALIZE_PASS_DEPENDENCY(Dependences)
INITIALIZE_PASS_DEPENDENCY(ScopInfo)
INITIALIZE_PASS_END(DeadCodeElim, "polly-dce",
                      "Polly - Remove dead iterations", false, false)

Pass* polly::createDeadCodeElimPass() {
  return new DeadCodeElim();
}
